Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

3장. 반드시 이해해야 할 핵심 개념들

2장에서 우리는 마이크로서비스가 가져오는 현실을 보았다.

  • 네트워크는 실패할 수 있고
  • 데이터는 잠시 어긋날 수 있으며
  • 디버깅은 복잡해지고
  • 운영 부담은 증가한다

그렇다면 질문이 생긴다.

이런 복잡성을 우리는 어떻게 통제하는가?

마이크로서비스는 감으로 설계하는 구조가 아니다.
몇 가지 핵심 개념을 이해하지 못하면
쉽게 “분산 모놀리스”가 된다.

이 장에서는 반드시 알아야 할 기본 개념들을 정리한다.


도메인 중심 설계(DDD)

마이크로서비스에서 가장 먼저 해야 할 일은
서비스의 경계를 정하는 것이다.

문제는, 경계를 “기술” 기준으로 나누면 실패한다는 점이다.

예를 들어,

  • Controller 서비스
  • Service 서비스
  • DAO 서비스

이렇게 나누는 것은 의미가 없다.

서비스는 비즈니스 책임 단위로 나누어야 한다.

도메인 중심 설계(DDD)는
이 경계를 정하기 위한 사고 방식이다.

핵심은 다음과 같다.

  • 하나의 서비스는 하나의 명확한 책임을 가진다
  • 다른 서비스의 내부 모델을 모른다
  • 각 서비스는 자신만의 언어와 규칙을 가진다

이때 사용하는 개념이
Bounded Context(경계가 정의된 영역) 다.

경계가 명확하지 않으면
서비스를 나눠도 서로 강하게 얽히게 된다.


응집력과 결합도

서비스를 나눴다고 해서
자동으로 독립성이 생기지는 않는다.

겉으로는 분리되었지만
실제로는 서로 강하게 의존하는 구조가 될 수 있다.

이를 판단하는 기준이
응집력과 결합도다.

응집력이 높다는 것은
한 서비스 안의 기능들이
같은 책임을 향해 움직이고 있다는 뜻이다.

결합도가 낮다는 것은
다른 서비스에 최소한으로 의존한다는 뜻이다.

만약 한 서비스가
다른 서비스의 데이터베이스를 직접 조회하거나
내부 모델을 알아야 동작한다면
그 구조는 이미 강하게 묶여 있는 상태다.

이런 구조를
“분산 모놀리스”라고 부른다.

서비스는 나뉘었지만
배포도, 수정도, 장애도 함께 움직인다.

마이크로서비스의 핵심은
얼마나 많이 나누었는가가 아니라
얼마나 잘 끊었는가다.


데이터베이스 분리

마이크로서비스의 가장 중요한 원칙 중 하나는

서비스마다 독립된 데이터 저장소를 가진다

는 것이다.

여기서 중요한 변화가 생긴다.

모놀리스에서는
여러 작업을 하나의 트랜잭션으로 묶을 수 있었다.

  • 주문 생성
  • 결제 성공
  • 포인트 적립

이 세 가지는 동시에 완료되거나
모두 취소되었다.

그러나 서비스가 분리되면
각 단계는 서로 다른 시스템에서 처리된다.

주문은 성공했지만
포인트 적립은 잠시 늦어질 수 있다.

사용자는 잠깐 동안
완전하지 않은 상태를 볼 수 있다.

이처럼
“시간 차이를 허용하는 데이터 모델”을
최종 일관성이라고 한다.

중요한 것은
데이터가 틀리는 것이 아니라
즉시 완전하지 않을 수 있다는 점을 설계로 관리하는 것이다.


서비스 간 통신 방식

서비스를 나누면 반드시 통신이 필요하다.

통신 방식은 크게 두 가지다.

동기 방식

요청을 보내고 즉시 응답을 기다린다.

  • REST
  • gRPC

장점은 직관적이다.
단점은 의존성이 강해진다는 것이다.

한 서비스가 느려지면
다른 서비스도 함께 느려진다.

비동기 방식

이벤트나 메시지를 보내고
응답을 기다리지 않는다.

  • 메시지 큐
  • 이벤트 스트림

장점은 느슨한 결합과 확장성이다.
단점은 설계가 복잡해진다는 점이다.

  • 메시지가 중복될 수 있고
  • 순서가 바뀔 수 있으며
  • 처리 지연이 발생할 수 있다

이때 필요한 개념이
멱등성(Idempotency) 이다.

같은 요청이 여러 번 와도
결과가 한 번 처리된 것처럼 유지되도록 설계하는 것이다.


장애 격리 설계

마이크로서비스 환경에서는
“실패하지 않도록” 설계하는 것이 아니라
“실패가 퍼지지 않도록” 설계해야 한다.

이를 위해 필요한 기본 개념들이 있다.

  • Timeout : 언제까지 기다릴 것인가
  • Retry : 다시 시도할 것인가
  • Circuit Breaker : 일정 수준 이상 실패하면 차단할 것인가
  • Rate Limit : 과도한 요청을 제한할 것인가

이 설계가 없다면
하나의 장애가 전체 시스템으로 번질 수 있다.


왜 이 개념들이 중요한가

마이크로서비스는 단순히 구조를 나누는 것이 아니다.

  • 경계를 잘못 나누면 복잡성이 증가하고
  • 데이터를 잘못 다루면 정합성이 무너지며
  • 통신을 잘못 설계하면 장애가 확산된다

이 개념들은 선택 사항이 아니라
생존 조건이다.


이 장의 결론

마이크로서비스는 기술이 아니라
사고 방식의 전환이다.

  • 책임을 어떻게 나눌 것인가
  • 데이터를 어떻게 다룰 것인가
  • 실패를 어떻게 설계할 것인가

이 질문에 답할 수 있을 때
비로소 전환을 논의할 준비가 된다.